﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;

namespace NameGenCore
{
    public class NameGenerator
    {
        private readonly Random _rnd;
        private readonly Dictionary<int, string> _names;
        private readonly Dictionary<NameType, string> _resources = new Dictionary<NameType, string>
                                                            {
                                                                {NameType.Female, "NameGenCore.Data.female.first.txt"},
                                                                {NameType.Male, "NameGenCore.Data.male.first.txt"},
                                                                {NameType.Surname, "NameGenCore.Data.last.txt"}
                                                            };

        /// <remarks>
        /// The bulk of processing occurs here in the constructor, so it is recommended that you reuse the same instance
        /// of this class where possible.  Once an instance has been created, the cost of calling Next is relatively minor.
        /// </remarks>
        public NameGenerator(NameType nameType)
        {
            _rnd = new Random(unchecked((int)DateTime.Now.Ticks));
            _names = GetNameDictionary(_resources[nameType]);
        }

        public string Next()
        {
            string rawName = _names[_rnd.Next(_names.Count)];
            string name;
            if (rawName.Contains("|"))
            {
                string[] tokens = rawName.Split('|');
                name = tokens[_rnd.Next(tokens.Length)];
            }
            else
            {
                name = rawName;
            }
            return name;
        }

        private static Dictionary<int, string> GetNameDictionary(string resourceName)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            var names = new Dictionary<int, string>();

            // ReSharper disable AssignNullToNotNullAttribute
            using (var reader = new StreamReader(assembly.GetManifestResourceStream(resourceName)))
            {
                // ReSharper restore AssignNullToNotNullAttribute

                int index = 0;
                while (reader.Peek() >= 0)
                {
                    string currentLine = reader.ReadLine();

                    // ReSharper disable PossibleNullReferenceException
                    string name = currentLine.Substring(0, currentLine.IndexOf(" "));
                    // ReSharper restore PossibleNullReferenceException

                    var cumulativeIndex = (int)(1000 * decimal.Parse(currentLine.Substring(21, 6)));

                    if (index > cumulativeIndex) index = cumulativeIndex;

                    while (index <= cumulativeIndex)
                    {
                        if (names.ContainsKey(index))
                        {
                            names[index] += "|" + name;
                        }
                        else
                        {
                            names.Add(index, name);
                        }
                        index++;
                    }
                }
            }
            return names;
        }
    }
}
